package com.nariano.server.domain.engine.droolsimpl;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;

import com.nariano.server.domain.entities.Area;
import com.nariano.server.domain.entities.City;
import com.nariano.server.domain.entities.Population;
import com.nariano.server.domain.entities.User;
import com.nariano.server.publisher.ClientPublisher;
import com.nariano.server.publisher.events.AreaDiscovered;
import com.nariano.server.services.cityservice.CityService;
import com.nariano.server.services.mapservice.MapService;

public class MoveFromCityAction {
    
    private static Random rand = new Random();

    private static final int THREE_UNITS = 3;
    
    @Autowired
    @Qualifier(value="mapService")
    private MapService mapService;
    
    @Autowired
	@Qualifier(value="clientPublisher")
    ClientPublisher clientPublisher;
    
    private Logger logger = Logger.getLogger(MoveFromCityAction.class.getCanonicalName());
    
    
    
    public MoveFromCityAction(MapService mapService) {
        this.mapService = mapService;
    }
    
    

    public MoveFromCityAction() {
    }


    public void moveFromCity(Area area) {
    	City city = area.getCity();
    	Assert.notNull(city);
    	
    	int prePopCount = city.getPopulationCount() + area.getPopulationCount();
		
        if (city.getPopulationCount()<3) {
        	return;
        }
        
        AreaDiscovered discoveredArea = null; 
        if (area.getPopulationCount()==0) {
        	discoveredArea = new AreaDiscovered(area);
		}
        
		Population areaPopulation = movePopulationFromCity(city);
		area.addPopulation(areaPopulation);
		mapService.updateAreas(area);
		if (logger.isLoggable(Level.FINE))  {
			logger.fine("Move out a " + areaPopulation.type().getName()+ " from city: " + city.getName());
			logger.fine("City population " + city.getPopulationCount());
			logger.fine("Area population " + area.getPopulationCount());
		}
		
		int postPopCount =  city.getPopulationCount() + area.getPopulationCount();
		if (prePopCount!=postPopCount) {
			logger.severe("Move out a " + areaPopulation.type().getName()+ " from city: " + city.getName());
			logger.severe("City population " + city.getPopulationCount());
			logger.severe("Area population " + area.getPopulationCount());
			logger.severe(String.format("Population leakage, expteced %d but got %d", prePopCount, postPopCount));
		}
		if (discoveredArea!=null) {
			clientPublisher.publish(discoveredArea);
		}

    }

    @Deprecated
    public void moveFromCity(City city) {
        if (city.getPopulation().isEmpty()) { 
            return; 
        }

		Population areaPopulation = movePopulationFromCity(city);
		Area area = mapService.getArea(city.getLocation());
		area.addPopulation(areaPopulation);
		mapService.updateAreas(area);
		if (logger.isLoggable(Level.FINE))  {
			logger.fine("Move out a " + areaPopulation.type().getName()+ " from city: " + city.getName());
		}

    }

    
    private Population movePopulationFromCity(City city) {
        Population movingPopulation = city.moveOutRandomPopulation();
        return movingPopulation;
        	
    }
 

}
